package com.blog.controller.admin;

import com.blog.constant.LogActions;
import com.blog.constant.WebConst;
import com.blog.controller.BaseController;
import com.blog.exception.BusinessException;
import com.blog.model.User;
import com.blog.service.log.LogService;
import com.blog.service.user.UserService;
import com.blog.utils.IPKit;
import com.blog.utils.ResultVoUtil;
import com.blog.utils.TaleUtils;
import com.blog.vo.ResultVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.constraints.NotBlank;
import java.io.IOException;

/**
 * 用户登录页面
 *
 * @author wmb
 *
 * @since 2021-2-7
 */
@Api("登录相关接口")
@Controller
@Validated
public class AuthController extends BaseController {

    private static final Logger LOGGER = LogManager.getLogger(AuthController.class);

    @Value("${error.time}")
    private Integer errorTimes;

    @Autowired
    @Qualifier("userService")
    private UserService userService;

    @Autowired
    @Qualifier("logService")
    private LogService logService;

    @ApiOperation("跳转登录页")
    @GetMapping(value = "/admin/login")
    public String login() {
        return "admin/login";
    }

    @ApiOperation("登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户名，用户名不允许为空", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "password", value = "密码，密码不允许为空", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "remember_me", value = "记住我", paramType = "query", dataType = "String", required = false)
    })
    @PostMapping("/admin/login")
    @ResponseBody
    public ResultVo toLogin(@ApiIgnore HttpServletRequest request,
                            @ApiIgnore HttpServletResponse response,
                            @NotBlank(message = "用户名不允许为空") @RequestParam("username") String username,
                            @NotBlank(message = "密码不允许为空") @RequestParam("password") String password,
                            @RequestParam(value = "remember_me", required = false) String rememberMe) {

        // 获取ip并过滤登录时缓存的bug
        String ip= IPKit.getIpAddrByRequest(request);
        Integer errorCount = cache.getSet("login_error_count", ip);

        try {
            User user = userService.login(username, password);
            request.getSession().setAttribute(WebConst.LOGIN_SESSION_KEY, user);
            if (StringUtils.isNotBlank(rememberMe)) {
                TaleUtils.setCookie(response, user.getUid());
            }
            logService.addLog(LogActions.LOGIN.getAction(), null, request.getRemoteAddr(), user.getUid());
        } catch (Exception e) {
            LOGGER.error("登录失败，错误：" + e.getMessage());
            errorCount = null == errorCount ? 1 : errorCount+1;
            if (errorCount > errorTimes) {
                return ResultVoUtil.error("您输入密码已经错误超过3次，请10分钟后尝试");
            }
            // 加入ip的过滤
            cache.hashSet("login_error_count", ip, errorCount, 10 * 60);
            String msg = "登录失败";
            if (e instanceof BusinessException) {
                msg = e.getMessage();
            } else {
                LOGGER.error(msg, e);
            }
            return ResultVoUtil.error(msg);
        }

        return ResultVoUtil.success();
    }

    @ApiOperation("注销")
    @GetMapping("/admin/logout")
    @ResponseBody
    public void logout(@ApiIgnore HttpServletRequest request,
                       @ApiIgnore HttpServletResponse response,
                       @ApiIgnore HttpSession session) throws IOException {
        // 销毁session
        session.removeAttribute(WebConst.LOGIN_SESSION_KEY);

        // 销毁cookie
        Cookie[] cookies = request.getCookies();
        for(Cookie cookie : cookies) {
            if(cookie.getName().equals(WebConst.USER_IN_COOKIE)) {
                // 找到对应的cookie
                // 通知浏览器删除对应的Cookie对象
                cookie.setMaxAge(0);
                //路径一定要写上，不然销毁不了
                cookie.setPath("/");
                // 重新响应
                response.addCookie(cookie);
            }
        }

        // 重定向
        response.sendRedirect("/admin/login");
    }
}
